//
//  DemoThread.m
//  ocdemo
//
//  Created by JIENING ZHANG on 2019/7/19.
//  Copyright © 2019 JIENING ZHANG. All rights reserved.
//

#import "DemoThread.h"

@implementation DemoThread

+ (void)taskA:(NSString *)desc {
    NSLog(@"taskA begin, %@, %@", desc, [NSThread currentThread]);
    [NSThread sleepForTimeInterval:2.0];
    NSLog(@"taskA end, %@, %@", desc, [NSThread currentThread]);
}

+ (void)taskB:(NSString *)desc {
    NSLog(@"taskB begin, %@, %@", desc, [NSThread currentThread]);
    [NSThread sleepForTimeInterval:1.0];
    NSLog(@"taskB end, %@, %@", desc, [NSThread currentThread]);
}

+ (void)taskC:(NSString *)desc {
    NSLog(@"taskC begin, %@, %@", desc, [NSThread currentThread]);
    [NSThread sleepForTimeInterval:1.0];
    NSLog(@"taskC end, %@, %@", desc, [NSThread currentThread]);
}

+ (void)taskD:(NSString *)desc {
    NSLog(@"taskD begin, %@, %@", desc, [NSThread currentThread]);
    [NSThread sleepForTimeInterval:3.5];
    NSLog(@"taskD end, %@, %@", desc, [NSThread currentThread]);
}

+ (void)run4TaskGCDGroupEnterLeave {
    // 0401
    // 4个任务ABCD
    // C依赖AB，使用 dispatch_group_enter dispatch_group_leave 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    
    dispatch_queue_t queue = dispatch_queue_create("gcd_queue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        [self taskD:@"D"];
    });
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        [self taskA:@"A"];
        dispatch_group_leave(group);
    });
    
    dispatch_async(queue, ^{
        [self taskB:@"B"];
        dispatch_group_leave(group);
    });
    
    dispatch_group_notify(group, queue, ^{
        [self taskC:@"C"];
    });
    
}

+ (void)run4TaskGCDGroupEnterLeaveOld {
    // 4个任务ABCD
    // C依赖AB，使用 dispatch_group_enter dispatch_group_leave 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    
    dispatch_queue_t queue = dispatch_queue_create("run4TaskGCD_CONCURRENT", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        [DemoThread taskA:@"GCDGroupEnterLeave"];
        dispatch_group_leave(group);
    });
    
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        [DemoThread taskB:@"GCDGroupEnterLeave"];
        dispatch_group_leave(group);
    });
    
    dispatch_group_notify(group, queue, ^{
        [DemoThread taskC:@"GCDGroupEnterLeave"];
    });
    
    dispatch_async(queue, ^{
        [DemoThread taskD:@"GCDGroupEnterLeave"];
    });
}

+ (void)run4TaskGCDGroup {
    // 0401
    // 4个任务ABCD
    // C依赖AB，使用 dispatch_group_async 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    
    dispatch_queue_t queue = dispatch_queue_create("gcd_queue", DISPATCH_QUEUE_CONCURRENT);

    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_async(group, queue, ^{
        [self taskD:@"D"];
    });
    dispatch_group_async(group, queue, ^{
        [self taskA:@"A"];
    });
    dispatch_group_async(group, queue, ^{
        [self taskB:@"B"];
    });
    dispatch_group_notify(group, queue, ^{
        [self taskC:@"C"];
    });
}

+ (void)run4TaskGCDGroupOld {
    // 4个任务ABCD
    // C依赖AB，使用 dispatch_group_async 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [DemoThread taskA:@"A"];
    });
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [DemoThread taskA:@"B"];
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        [DemoThread taskC:@"C"];
    });
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [DemoThread taskD:@"D"];
    });
}

+ (void)run4TaskGCDGroup__ {
    // 4个任务ABCD
    // C依赖AB，使用 dispatch_group_async 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    dispatch_queue_t myQueue = dispatch_queue_create("com.gcd.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, myQueue, ^{
       [self.class taskA:@"A"];
    });
    dispatch_group_async(group, myQueue, ^{
       [self.class taskB:@"B"];
    });
    
    dispatch_group_notify(group, myQueue, ^{
        
        dispatch_group_async(group, myQueue, ^{
               [self.class taskC:@"C"];
           });
    });
    dispatch_group_async(group, myQueue, ^{
       [self.class taskD:@"D"];
    });
}

+ (void)run4TaskGCDGroup__o {
    // 4个任务ABCD
    // C依赖AB，使用 dispatch_group_async 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    
    dispatch_queue_t queue = dispatch_queue_create("run4TaskGCD_CONCURRENT", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{
        [DemoThread taskA:@"GCDGroup"];
    });
    
    dispatch_group_async(group, queue, ^{
        [DemoThread taskB:@"GCDGroup"];
    });
    
    dispatch_group_notify(group, queue, ^{
        [DemoThread taskC:@"GCDGroup"];
    });
    
    dispatch_async(queue, ^{
        [DemoThread taskD:@"GCDGroup"];
    });
}

+ (void)run4TaskGCD {
    // 0401
    // 4个任务ABCD
    // C依赖AB完成，使用 dispatch_async dispatch_barrier_async  实现
    // D和ABC无关，期望尽量快执行完成所有任务
    dispatch_queue_t queue = dispatch_queue_create("gcd_queue", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{
        [self taskD:@"D"];
    });
    
    dispatch_async(queue, ^{
        [self taskA:@"A"];
    });
    
    dispatch_async(queue, ^{
        [self taskB:@"B"];
    });
    
    dispatch_barrier_async(queue, ^{
        [self taskC:@"C"];
    });
}

+ (void)run4TaskGCDOld {
    // 4个任务ABCD
    // C依赖AB完成，使用 dispatch_async dispatch_barrier_async  实现
    // D和ABC无关，期望尽量快执行完成所有任务
    dispatch_queue_t queue = dispatch_queue_create("aaa", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        [DemoThread taskA:@"A"];
    });
    
    dispatch_async(queue, ^{
        [DemoThread taskB:@"B"];
    });
    
    dispatch_barrier_async(queue, ^{
        [DemoThread taskC:@"C"];
    });
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [DemoThread taskD:@"D"];
    });
}

+ (void)run4TaskGCD__ {
    // 4个任务ABCD
    // C依赖AB完成，使用 dispatch_async dispatch_barrier_async  实现
    // D和ABC无关，期望尽量快执行完成所有任务
    dispatch_queue_t myQueue = dispatch_queue_create("com.gcd.barrier.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(myQueue, ^{
        [self.class taskA:@"A"];
    });
    dispatch_async(myQueue, ^{
        [self.class taskB:@"B"];
    });
    dispatch_barrier_async(myQueue,^{
        [self.class taskC:@"C"];
    });
    dispatch_async(myQueue, ^{
        [self.class taskD:@"D"];
    });
}

+ (void)run4TaskGCD__o {
    // 4个任务ABCD
    // C依赖AB完成，使用 dispatch_async dispatch_barrier_async  实现
    // D和ABC无关，期望尽量快执行完成所有任务
    
    // dispatch_barrier_async 的说明文档有这个信息。
    // If the queue you pass to this function is a serial queue or one of the global concurrent queues, this function behaves like the dispatch_async function.
    // 如果使用 串行队列 或是 全局队列，它的行为将如同 dispatch_async，所以dispatch_barrier_async 使用自己创建的并行队列才产生预期行为。
    dispatch_queue_t queue = dispatch_queue_create("run4TaskGCD_CONCURRENT", DISPATCH_QUEUE_CONCURRENT);
    // dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    dispatch_async(queue, ^{
        
        dispatch_async(queue, ^{
            [DemoThread taskA:@"GCDBarrierAsync"];
        });
        
        dispatch_async(queue, ^{
            [DemoThread taskB:@"GCDBarrierAsync"];
        });
        
        dispatch_barrier_async(queue, ^{
            [DemoThread taskC:@"GCDBarrierAsync"];
        });
    });
    //dispatch_async(queue, ^{ //这是错的
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [DemoThread taskD:@"GCDBarrierAsync"];
    });
}

+ (void)run4TaskOperation {
    // 0401
    // 4个任务ABCD
    // C依赖AB完成，使用 NSOperation NSOperationQueue 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 3;

    NSBlockOperation *a = [NSBlockOperation blockOperationWithBlock:^{
        [self taskA:@"a"];
    }];
    NSBlockOperation *b = [NSBlockOperation blockOperationWithBlock:^{
        [self taskB:@"b"];
    }];
    NSBlockOperation *c = [NSBlockOperation blockOperationWithBlock:^{
        [self taskC:@"c"];
    }];
    NSBlockOperation *d = [NSBlockOperation blockOperationWithBlock:^{
        [self taskD:@"d"];
    }];
    
    [c addDependency:a];
    [c addDependency:b];
    
    [queue addOperation:d];
    [queue addOperation:a];
    [queue addOperation:b];
    [queue addOperation:c];

}

+ (void)run4TaskOperationOld {
    // 4个任务ABCD
    // C依赖AB完成，使用 NSOperation NSOperationQueue 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    NSOperationQueue *queue=[[NSOperationQueue alloc] init];
        //创建操作
    NSBlockOperation *operation1=[NSBlockOperation blockOperationWithBlock:^(){
        [DemoThread taskA:@"A"];
    }];
    NSBlockOperation *operation2=[NSBlockOperation blockOperationWithBlock:^(){
        [DemoThread taskB:@"B"];
    }];
    NSBlockOperation *operation3=[NSBlockOperation blockOperationWithBlock:^(){
        [DemoThread taskC:@"C"];
    }];
    NSBlockOperation *operation4=[NSBlockOperation blockOperationWithBlock:^(){
        [DemoThread taskD:@"D"];
    }];
    
    [operation3 addDependency:operation1];
    [operation3 addDependency:operation2];
        //将操作添加到队列中去
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
    [queue addOperation:operation4];
}

+ (void)run4TaskOperation__ {
    // 4个任务ABCD
    // C依赖AB完成，使用 NSOperation NSOperationQueue 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    
    NSOperationQueue *myQueue =[[NSOperationQueue alloc] init];
    
    NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^(){
           [self.class taskA:@"A"];
        }];
    
    NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^(){
       [self.class taskB:@"B"];
    }];
    
    
    NSBlockOperation *operationC = [NSBlockOperation blockOperationWithBlock:^(){
       [self.class taskC:@"C"];
    }];
    
    NSBlockOperation *operationD = [NSBlockOperation blockOperationWithBlock:^(){
          [self.class taskD:@"D"];
    }];
    [operationC addDependency:operationA];
    [operationC addDependency:operationB];
    
    
    [myQueue addOperation:operationA];
    [myQueue addOperation:operationB];
    [myQueue addOperation:operationC];
    [myQueue addOperation:operationD];
}

+ (void)run4TaskOperation__o {
    // 4个任务ABCD
    // C依赖AB完成，使用 NSOperation NSOperationQueue 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    
    NSOperation *taskA = [NSBlockOperation blockOperationWithBlock:^{
        [DemoThread taskA:@"NSOperation"];
    }];
    
    NSOperation *taskB = [NSBlockOperation blockOperationWithBlock:^{
        [DemoThread taskB:@"NSOperation"];
    }];
    
    NSOperation *taskC = [NSBlockOperation blockOperationWithBlock:^{
        [DemoThread taskC:@"NSOperation"];
    }];
    
    NSOperation *taskD = [NSBlockOperation blockOperationWithBlock:^{
        [DemoThread taskD:@"NSOperation"];
    }];
    
    [taskC addDependency:taskA];
    [taskC addDependency:taskB];
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    [queue addOperation:taskA];
    [queue addOperation:taskB];
    [queue addOperation:taskC];
    [queue addOperation:taskD];
    
}

+ (void)run4TaskNSThreadSemaphore {
    // 4个任务ABCD
    // C依赖AB完成，使用 NSThread dispatch_semaphore 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    
    dispatch_queue_t myQueue = dispatch_queue_create("com.gcd.barrier.queue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    dispatch_async(myQueue, ^{
         [self.class taskA:@"A"];
         dispatch_semaphore_signal(semaphore);
     });
    dispatch_async(myQueue, ^{
        [self.class taskB:@"B"];
        dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    dispatch_async(myQueue, ^{
        [self.class taskC:@"C"];
    });
    dispatch_async(myQueue, ^{
        [self.class taskD:@"D"];
    });
}

+ (void)run4TaskNSThreadSemaphore__ {
    // 4个任务ABCD
    // C依赖AB完成，使用 NSThread dispatch_semaphore 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    
    dispatch_semaphore_t sa = dispatch_semaphore_create(0);
    NSThread *tA = [[NSThread alloc]initWithBlock:^{
        [DemoThread taskA:@"NSThreadSemaphore"];
        
        dispatch_semaphore_signal(sa);
    }];
    
    dispatch_semaphore_t sb = dispatch_semaphore_create(0);
    NSThread *tB = [[NSThread alloc]initWithBlock:^{
        [DemoThread taskB:@"NSThreadSemaphore"];
        
        dispatch_semaphore_signal(sb);
    }];
    
    NSThread *tC = [[NSThread alloc]initWithBlock:^{
        
        dispatch_semaphore_wait(sa, DISPATCH_TIME_FOREVER);
        dispatch_semaphore_wait(sb, DISPATCH_TIME_FOREVER);
        
        [DemoThread taskC:@"NSThreadSemaphore"];
    }];
    
    NSThread *tD = [[NSThread alloc]initWithBlock:^{
        [DemoThread taskD:@"NSThreadSemaphore"];
    }];
    
    [tA start];
    [tB start];
    [tC start];
    [tD start];
}

+ (void)run4TaskNSThreadLock {
    // 4个任务ABCD
    // C依赖AB完成，使用 NSThread NSLock 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    NSLock *lock = [[NSLock alloc] init];
    __block BOOL aEnd = NO;
    __block BOOL bEnd = NO;
    __block BOOL cBegin = NO;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [DemoThread taskA:@"A"];
        [lock lock];
        aEnd = YES;
        if (bEnd == YES && cBegin == NO) {
            cBegin = YES;
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                [DemoThread taskC:@"C"];
            });
        }
        [lock unlock];
    });
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [DemoThread taskB:@"B"];
        [lock lock];
        bEnd = YES;
        if (aEnd == YES && cBegin == NO) {
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                [DemoThread taskC:@"C"];
            });
        }
        [lock unlock];
    });
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [DemoThread taskD:@"D"];
    });
}

+ (void)run4TaskNSThreadLock__ {
    // 4个任务ABCD
    // C依赖AB完成，使用 NSThread NSLock 实现
    // D和ABC无关，期望尽量快执行完成所有任务
    NSLock *lA = [[NSLock alloc]init];

    NSThread *tA = [[NSThread alloc]initWithBlock:^{
        [DemoThread taskA:@"NSThreadNSLock"];
        
        [lA unlock];
    }];
    
    NSLock *lB = [[NSLock alloc]init];

    NSThread *tB = [[NSThread alloc]initWithBlock:^{
        [DemoThread taskB:@"NSThreadNSLock"];
        
        [lB unlock];
    }];
    
    NSThread *tC = [[NSThread alloc]initWithBlock:^{
        
        [lA lock];
        [lB lock];
        
        [DemoThread taskC:@"NSThreadNSLock"];
        
        [lB unlock];
        [lA unlock];
    }];
    
    NSThread *tD = [[NSThread alloc]initWithBlock:^{
        [DemoThread taskD:@"NSThreadNSLock"];
    }];
    
    [lA lock];
    [tA start];
    
    [lB lock];
    [tB start];
    
    [tC start];
    [tD start];
}


+ (void)demoLogic {
    //[self run4TaskNSThreadLock];
    //[self run4TaskNSThreadSemaphore];
    
    //[self run4TaskGCD];
    //[self run4TaskGCD__o];
    //[self run4TaskGCDGroup];
    [self run4TaskGCDGroupEnterLeave];
    
    //[self run4TaskOperation];
}

@end
